package com.companyname.demo.cod.filter;

import com.alibaba.fastjson.JSONObject;
import com.companyname.demo.cod.domain.AjaxResult;
import com.companyname.demo.cod.domain.UserInfo;
import com.companyname.demo.cod.util.IpUtil;
import com.companyname.demo.cod.util.JwtUtil;
import com.companyname.demo.cod.util.MapBeanConvertUtil;
import com.companyname.demo.cod.util.PathMatcherUtil;
import com.companyname.demo.cod.util.impl.AntPathMatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Base64Utils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@WebFilter(filterName = "gatewayFilter", description = "网关过滤器：jwt的校验、资源的处理", urlPatterns = "/*")
@Order(1)
@Slf4j
public class GatewayFilter implements Filter {
    private String filterName;
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${whiteUrlList}")
    private String whiteUrlList;
    private static final PathMatcherUtil pathMatcherUtil = new AntPathMatcher();
    private static final String USER_TOKEN="user_token";
    private static final String FILE_USER_TOKEN="file_user_token";


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        filterName = filterConfig.getFilterName();
        log.info("{}过滤器准备初始化...", filterName);

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String servletPath = req.getServletPath();
        String sourceIp = IpUtil.getIpAddr(req);
        if (!servletPath.contains(".")) {//只打印API请求
            log.info("用户[{}]请求的地址={}", sourceIp, servletPath);
        }
        //1.欢迎页的跳转
        if ("/".equals(servletPath)) {
            ((HttpServletResponse) response).sendRedirect("/views/html/index.html");
            return;//不加return而放行的话，会报异常：Cannot call sendError() after the response has been committed
        }
        //2.URL白名单的过滤：如果是白名单则放行,结束方法
        if (whiteUrlList != null && whiteUrlList.trim().length() > 0) {
            for (String whiteUrl : whiteUrlList.split(",")) {
                String uriPattern = whiteUrl.trim();
                // 支持ANT表达式
                if (pathMatcherUtil.match(uriPattern, servletPath)) {
                    //log.info("{}是白名单，放行", servletPath);
                    chain.doFilter(request, response);
                    return;
                }
            }
        }
        //3.从请求头获取首部字段userToken并校验
        String userToken = req.getHeader(USER_TOKEN);
        //log.info("请求头获取到的userToken={}", userToken);
        //文件导出、下载的API，请求头没有userToken，需要从request.parameter里获取fileUserToken
        if (StringUtils.isBlank(userToken)){
            userToken  = req.getParameter(FILE_USER_TOKEN);
        }
        try {
            AjaxResult checkResult = JwtUtil.checkJwt(userToken);
            if (checkResult.getCode() != AjaxResult.Type.SUCCESS.getCode()) {
                log.error("jwt校验不通过！{}", checkResult.toString());
                ((HttpServletResponse) response).sendError(checkResult.getCode(), checkResult.getMessage());
            } else {//jwt校验成功后：
                //log.info("jwt校验通过！");
                //从jwt.payload中获取userName
                String requestJwtPayload = userToken.split("\\.")[1];
                JSONObject payloadJSON = (JSONObject) JSONObject.parse(Base64Utils.decode(requestJwtPayload.getBytes()));
                String userName = (String) payloadJSON.get("userName");
                //重置jwtsalt有效时间
                redisTemplate.opsForValue().getOperations().expire("jwtsalt:" + userName, 24, TimeUnit.HOURS);
                //根据userName从redis中获取UserInfo放入Request.attributes中，供业务逻辑使用
                Map<String, Object> userInfoMap = (Map<String, Object>) redisTemplate.opsForHash().get("userInfo", userName);
                UserInfo userInfo = (UserInfo) MapBeanConvertUtil.convertMap2Bean(UserInfo.class, userInfoMap);
                request.setAttribute("userInfo", userInfo);
                //放行
                chain.doFilter(request, response);
            }
        } catch (Exception e) {
            log.error("校验jwt异常！", e);
            ((HttpServletResponse) response).sendError(AjaxResult.Type.INVALID_TOKEN.getCode(), AjaxResult.Type.INVALID_TOKEN.getDesc());//不合法的token
        }


    }

    @Override
    public void destroy() {
        log.info("{}过滤器准备销毁...", filterName);
    }
}
